/*
Copyright 2006 by Sean Luke
Licensed under the Academic Free License version 3.0
See the file "LICENSE" for more information
*/


package exp.parity;
import exp.util.*;
import ec.app.parity.*;
import ec.util.*;
import ec.*;
import ec.gp.*;
import ec.gp.koza.*;
import ec.simple.*;

/* 
 * Parity.java
 * 
 * Created: Mon Nov  1 15:46:19 1999
 * By: Sean Luke
 */

/**
 * Parity implements the family of <i>n</i>-[even|odd]-Parity problems up 
 * to 32-parity.  Read the README file in this package for information on
 * how to set up the parameter files to your liking -- it's a big family.
 *
 * <p>The Parity family evolves a boolean function on <i>n</i> sets of bits,
 * which returns true if the number of 1's is even (for even-parity) or odd
 * (for odd-parity), false otherwise. 
 *
 <p><b>Parameters</b><br>
 <table>
 <tr><td valign=top><i>base</i>.<tt>data</tt><br>
 <font size=-1>classname, inherits or == ec.app.parity.ParityData</font></td>
 <td valign=top>(the class for the prototypical GPData object for the Parity problem)</td></tr>
 <tr><td valign=top><i>base</i>.<tt>even</tt><br>
 <font size=-1> bool = <tt>true</tt> (default) or <tt>false</tt></font></td>
 <td valign=top>(is this even-parity (as opposed to odd-parity)?)</td></tr>
 <tr><td valign=top><i>base</i>.<tt>bits</tt><br>
 <font size=-1> 2 &gt;= int &lt;= 31</font></td>
 <td valign=top>(The number of data bits)</td></tr>
 </table>

 <p><b>Parameter bases</b><br>
 <table>
 <tr><td valign=top><i>base</i>.<tt>data</tt></td>
 <td>species (the GPData object)</td></tr>
 </table>
 *
 * @author Sean Luke
 * @version 1.0 
 */

public class Parity2 extends Parity// implements SimpleProblemForm
    {
    public Object clone()
        {
        Parity myobj = (Parity2) (super.clone());
        myobj.input = (ParityData)(input.clone());
        return myobj;
        }


    public void evaluate(final EvolutionState state, 
                         final Individual ind, 
                         final int threadnum)
        {
        if (!ind.evaluated)  // don't bother reevaluating
            {
            int sum = 0;
                
            for(bits=0;bits<totalSize;bits++)
                {
                int tb = 0;
                // first, is #bits even or odd?
                for(int b=0;b<numBits;b++)
                    tb += (bits >>> b) & 1;
                tb &= 1;  // now tb is 1 if we're odd, 0 if we're even

                ((GPIndividual)ind).trees[0].child.eval(
                    state,threadnum,input,stack,((GPIndividual)ind),this);

                if ((doEven && ((input.x & 1) != tb)) ||
                    ((!doEven) && ((input.x & 1) == tb)))
                    sum++;
                }
                
            // the fitness better be KozaFitness!
            //KozaFitness f = ((KozaFitness)ind.fitness);
            //f.setStandardizedFitness(state,(float)(totalSize - sum));
            //f.hits = sum;
            ((SimpleFitness)(ind.fitness)).setFitness( state, (float)sum/(float)totalSize, sum==totalSize );
            ind.evaluated = true;
            }
        
        // Output if whole population is evaluated
        boolean popevaluated = true;
        for(int i=0; i<state.population.subpops[0].individuals.length; i++)
            popevaluated = (popevaluated && state.population.subpops[0].individuals[i].evaluated);
        if(popevaluated)
            {
            MyExpOutput myout = new MyExpOutput(state);
            myout.printFit(state, state.population);
        // Check GP tree size for testing
        //int GPTreeSize = 0;
        //for( int j = 0 ; j < state.population.subpops[0].individuals.length ; j++ )
        //{
        //    GPTreeSize += state.population.subpops[0].individuals[j].size();
        //}
        //System.out.println(state.generation+"  Averaged GP Tree Size: " + ((float)GPTreeSize/(float)state.population.subpops[0].individuals.length));
            }
        }
    
    // Describe    
    public void describe(final Individual ind, 
                         final EvolutionState state, 
                         final int threadnum, final int log,
                         final int verbosity)
        {
        MyExpOutput myout = new MyExpOutput(state);
        myout.printFit(state, state.population);
        return;
        }
    }
